package com.duoqin.chat.ui;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.chat.Chat;
import com.duoqin.guard.GuardServiceManager;
import com.duoqin.chat.IDuoqinChatCallback;
import com.duoqin.chat.utils.ChatConfig;
import com.duoqin.chat.utils.PopupWindowList;
import com.duoqin.common.EventRecordManager;
import com.duoqin.common.ui.AbsActivity;
import com.duoqin.common.utils.QNHelper;
import com.duoqin.common.utils.Utils;
import com.duoqin.emoji.EmojiManager;
import com.duoqin.syncassistant.R;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class ChatAbsActivity extends AbsActivity implements LoaderManager.LoaderCallbacks<Cursor> {

    protected static final long SEND_TIMEOUT = 10 * DateUtils.SECOND_IN_MILLIS;
    protected static final long MAX_CHAT_LENGTH = 60;
    protected final ArrayList<Integer> mMenuList = new ArrayList<>();

    protected Activity mActivity;
    protected AudioManager mAudioManager;
    protected ClipboardManager mClipboardManager;
    protected ClipData mClipData;
    protected MediaPlayer mMediaPlayer;
    protected GuardServiceManager mGuardServiceManager;

    protected AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
            new AudioManager.OnAudioFocusChangeListener() {

                @Override
                public void onAudioFocusChange(int focusChange) {
                    switch (focusChange) {
                        case AudioManager.AUDIOFOCUS_LOSS:
                        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: { // phone ring, etc.
                            onAudioFocusLost();
                            break;
                        }
                    }
                }
            };

    protected void onAudioFocusLost() {
        if (mMediaPlayer != null) {
            try {
                if (mMediaPlayer.isPlaying()) {
                    mMediaPlayer.stop();
                }
            } catch (Exception e) {
//                e.printStackTrace();
            }
        }
    }

    private ChatAdapter mChatAdapter;
    private LayoutInflater mLayoutInflater;
    protected ListView mListView;
    protected View mDimBgView;
    private long mCurrentPlayChatId;
    protected String mName;
    private PopupWindowList mPopupWindowList;


    private IDuoqinChatCallback mCallback = new IDuoqinChatCallback.Stub() {
        public void messageReceived(String chatId) {
            Log.i(TAG, "onMessageReceived chatId = " + chatId);
            Message message = new Message();
            message.what = MSG_UPDATE_UI;
            message.obj = chatId;
            mHandler.sendMessage(message);
        }

        public void failureReport(String status) {
            Log.i(TAG, "failureReport status = " + status);
            Message message = new Message();
            message.what = MSG_HANDLE_FAILURE;
            message.obj = status;
            mHandler.sendMessage(message);
        }
    };

    protected int mRecordingLength;
    protected static final int MSG_UPDATE_UI = 0;
    protected static final int MSG_SPEECH_RECORDING_TIMER = 1;
    public static final int MSG_UPLOAD_MEDIA_SUCCESS = 2;
    public static final int MSG_UPLOAD_MEDIA_FAIL = 3;
    protected static final int MSG_PLAY_VOICE = 4;
    protected static final int MSG_HANDLE_FAILURE = 5;
    @SuppressLint("HandlerLeak")
    protected Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_UI: {
                    if (mChatAdapter != null) {
                        mChatAdapter.notifyDataSetChanged();
                    }
                    break;
                }
                case MSG_SPEECH_RECORDING_TIMER: {
                    mRecordingLength++;
                    if (mRecordingLength < MAX_CHAT_LENGTH) {
                        onRecordingTimerTick();
                        sendEmptyMessageDelayed(MSG_SPEECH_RECORDING_TIMER, 1000);
                    } else {
                        stopRecordingAndSendMessage();
                    }
                    break;
                }
                case MSG_UPLOAD_MEDIA_SUCCESS: {
                    if (msg.obj instanceof Chat) {
                        Chat chat = (Chat) msg.obj;
                        sendChatMessage(chat);
                        EventRecordManager.getInstance(getApplicationContext()).onEvent("CHAT",
                                chat.message_type);
                    }
                    break;
                }
                case MSG_UPLOAD_MEDIA_FAIL: {
                    if (msg.obj instanceof Chat) {
                        Chat chat = (Chat) msg.obj;
                        Chat.clearServerMediaPath(getContentResolver(), chat.id + "");
                    }
                    removeMessages(MSG_UPDATE_UI);
                    sendEmptyMessage(MSG_UPDATE_UI);
                    break;
                }
                case MSG_PLAY_VOICE: {
                    if (msg.obj != null) {
                        play((String) msg.obj);
                    } else {
                        Toast.makeText(getApplicationContext(),
                                R.string.audio_file_download_failed_or_expired, Toast.LENGTH_SHORT)
                                .show();
                    }
                    break;
                }
                case MSG_HANDLE_FAILURE: {
                    if (msg.obj instanceof String) {
                        handleFailure((String) msg.obj);
                    }
                    break;
                }
            }
        }
    };

    protected void handleFailure(String status) {
        Log.i(TAG, "handleFailure " + status);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = this;
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        mClipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        mLayoutInflater = LayoutInflater.from(this);

        mGuardServiceManager = GuardServiceManager.getInstance(this, mCallback, null);

        EventRecordManager.getInstance(this);
    }

    protected void setupTitle(String title) {
        mToolbar = findViewById(R.id.toolbar);
        mToolbar.setTitle(title);
    }

    protected void initView() {
        mDimBgView = findViewById(R.id.mask);
        mListView = findViewById(R.id.chat_list);

        mChatAdapter = new ChatAdapter(this, null, 0);
        mListView.setAdapter(mChatAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ViewHolder holder = (ViewHolder) view.getTag();
                final Chat chat = (Chat) holder.bodyView.getTag();
                if (!chat.sent) {
                    resendMessage(chat);
                } else {
                    mCurrentPlayChatId = chat.id;
                    chat.read = true;
                    if (mActivity instanceof ChatFavoritesActivity) {
                        Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI, chat);
                    } else {
                        Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                    if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)) {
                        if (TextUtils.isEmpty(chat.media_path)) {
                            downloadVoiceAndPlay(chat, true);
                        } else {
                            File file = new File(chat.media_path);
                            if (file.exists()) {
                                playVoice(chat.media_path);
                            } else {
                                downloadVoiceAndPlay(chat, true);
                            }
                        }
//                } else {
//                    Intent intent = new Intent(getApplicationContext(), ReadMessageActivity.class);
//                    intent.putExtra(ReadMessageActivity.INTENT_EXTRA_CHAT, chat);
//                    if (mActivity instanceof ChatFavoritesActivity) {
//                        intent.putExtra(ReadMessageActivity.INTENT_EXTRA_FAVORITE, true);
//                    }
//                    startActivity(intent);
                    }
                }
            }
        });

        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                ViewHolder holder = (ViewHolder) view.getTag();
                if (holder == null) return false;
                final Chat chat = (Chat) holder.bodyView.getTag();
                if (chat == null) return false;
                prepareMenuItem(chat);
                showPopWindows(view, chat);
                return true;
            }
        });
    }

    private void showPopWindows(View view, final Chat chat) {
        List<String> dataList = new ArrayList<>();
        for (int i = 0; i < mMenuList.size(); i++) {
            if(!getString(mMenuList.get(i)).equals("")){
                dataList.add(getString(mMenuList.get(i)));
            }
        }
        if (mPopupWindowList == null) {
            mPopupWindowList = new PopupWindowList(view.getContext());
        }
        mPopupWindowList.setAnchorView(view);
        mPopupWindowList.setItemData(dataList);
        mPopupWindowList.setModal(true);
        mPopupWindowList.show();
        mPopupWindowList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (R.string.menu_delete == mMenuList.get(position)) {
                    if (mActivity instanceof ChatFavoritesActivity) {
                         Chat.delete(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI,
                                chat);
                    } else {
                       Chat.delete(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                } else if (R.string.menu_add_favorites == mMenuList.get(position)) {
                    Chat favoriteChat = new Chat(chat);
                    if (!TextUtils.isEmpty(mName)) {
                        favoriteChat.name = mName;
                    }
                    Chat.addToFavorite(getContentResolver(), favoriteChat);
                } else if (R.string.menu_to_text == mMenuList.get(position)) {
                    chat.read = true;
                    if (mActivity instanceof ChatFavoritesActivity) {
                        Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI,
                                chat);
                    } else {
                        Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                    Intent intent = new Intent(getApplicationContext(),
                            ReadMessageActivity.class);
                    intent.putExtra(ReadMessageActivity.INTENT_EXTRA_CHAT, chat);
                    if (mActivity instanceof ChatFavoritesActivity) {
                        intent.putExtra(ReadMessageActivity.INTENT_EXTRA_FAVORITE, true);
                    }
                    startActivity(intent);
                } else if (R.string.menu_resend == mMenuList.get(position)) {
                    resendMessage(chat);
                } else if (android.R.string.copy == mMenuList.get(position)) {
                    onCopyClicked(chat);
                }
                mPopupWindowList.hide();
            }
        });
    }

    protected void onCopyClicked(Chat chat) {
    }

    protected void prepareMenuItem(Chat chat) {
        mMenuList.clear();
    }

    @Override
    protected void onResume() {
        super.onResume();
        GuardServiceManager.registerChatCallback(mCallback);
    }

    @Override
    protected void onPause() {
        super.onPause();
        GuardServiceManager.registerChatCallback(null);
    }

    @Override
    public void onStart() {
        // Initializes the loader in onStart
        getLoaderManager().initLoader(0, null, this);
        super.onStart();
        mAudioManager.requestAudioFocus(mAudioFocusChangeListener, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mCurrentPlayChatId = 0;
        stopPlay();
        mHandler.removeCallbacksAndMessages(null);
        mAudioManager.abandonAudioFocus(mAudioFocusChangeListener);
    }

    /* adjust volume is conflicting with list scrolling
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_DOWN :{
                if (mMediaPlayer != null) {
                    try {
                        if (mMediaPlayer.isPlaying()) {
                            return true;
                        }
                    } catch (Exception e) {
//                        e.printStackTrace();
                    }
                }
                break;
            }
            case KeyEvent.KEYCODE_DPAD_UP :{
                if (mMediaPlayer != null) {
                    try {
                        if (mMediaPlayer.isPlaying()) {
                            return true;
                        }
                    } catch (Exception e) {
//                        e.printStackTrace();
                    }
                }
                break;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_DOWN :{
                if (mMediaPlayer != null) {
                    try {
                        if (mMediaPlayer.isPlaying()) {
                            mAudioManager.adjustStreamVolume(
                                    AudioManager.STREAM_MUSIC,
                                    AudioManager.ADJUST_LOWER,
                                    AudioManager.FLAG_PLAY_SOUND);
                            return true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            }
            case KeyEvent.KEYCODE_DPAD_UP :{
                if (mMediaPlayer != null) {
                    try {
                        if (mMediaPlayer.isPlaying()) {
                            mAudioManager.adjustStreamVolume(
                                    AudioManager.STREAM_MUSIC,
                                    AudioManager.ADJUST_RAISE,
                                    AudioManager.FLAG_PLAY_SOUND);
                            return true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            }
        }
        return super.onKeyUp(keyCode, event);
    }
    */

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        CursorLoader loader = new CursorLoader(getApplicationContext(), Chat.Columns.CONTENT_URI,
                Chat.Columns.CHAT_QUERY_COLUMNS, null, null,
                Chat.Columns.DEFAULT_SORT_ORDER);
        return loader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if (mChatAdapter != null) {
            mChatAdapter.swapCursor(cursor);
            if (mChatAdapter.getCount() > 0
                    && mListView.getSelectedItemPosition() >= mChatAdapter.getCount()) {
                mListView.setSelection(mChatAdapter.getCount() - 1);
            }
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        if (mChatAdapter != null) {
            mChatAdapter.swapCursor(null);
        }
    }

    private class ViewHolder {
        View view, bodyView;
        TextView nameTV, bodyTV, timeTV, voiceLengthTV;
        ImageView imageView;

        ViewHolder(View view) {
            this.view = view;
            this.bodyView = view.findViewById(R.id.body_view);
            this.nameTV = view.findViewById(R.id.name);
            this.bodyTV = view.findViewById(R.id.body);
            this.timeTV = view.findViewById(R.id.timestamp);
            this.voiceLengthTV = view.findViewById(R.id.voice_length);
            this.imageView = view.findViewById(R.id.image);
        }
    }

    private class ChatAdapter extends CursorAdapter {
        private Context mContext;
        private EmojiManager mEmojiManager;
        private int mEmojiTextSize;

        private ChatAdapter(Context context, Cursor c, int flags) {
            super(context, c, flags);
            mContext = context;
            mEmojiManager = EmojiManager.getInstance();
            mEmojiTextSize = getResources().getDimensionPixelSize(R.dimen.duoqin_text_size_medium);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (!getCursor().moveToPosition(position)) {
                throw new IllegalStateException("couldn't move cursor to position " + position);
            }
            View v;
            if (convertView == null) {
                v = newView(mContext, getCursor(), parent);
            } else {
                final Chat chat = new Chat(getCursor());
                ViewHolder holder = (ViewHolder) convertView.getTag();
                final Chat holderChat = (Chat) holder.bodyView.getTag();
                if (holderChat != null && !holderChat.type.equalsIgnoreCase(chat.type)) {
                    convertView = newView(mContext, getCursor(), parent);
                }
                v = convertView;
            }
            bindView(v, mContext, getCursor());
            return v;
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            final Chat chat = new Chat(cursor);
            View ret;
            if (Chat.Columns.CHAT_TYPE_IN.equalsIgnoreCase(chat.type)) {
                ret = mLayoutInflater.inflate(R.layout.list_item_chat_receive, parent, false);
            } else {
                ret = mLayoutInflater.inflate(R.layout.list_item_chat_send, parent, false);
            }
            ViewHolder holder = new ViewHolder(ret);
            ret.setTag(holder);
            return ret;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            final Chat chat = new Chat(cursor);
            AnimationDrawable drawableStart = null;
            AnimationDrawable drawableEnd = null;
            AnimationDrawable animationDrawable = null;
            final ViewHolder holder = (ViewHolder) view.getTag();
            holder.bodyView.setTag(chat);
            if (mActivity instanceof ChatFavoritesActivity) {
                holder.timeTV.setText(DateUtils.formatDateTime(getApplicationContext(),
                        chat.time_stamp, DateUtils.FORMAT_SHOW_DATE
                                | DateUtils.FORMAT_NUMERIC_DATE));
            } else {
                holder.timeTV.setText(DateUtils.formatDateTime(getApplicationContext(),
                        chat.time_stamp, DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE
                                | DateUtils.FORMAT_NUMERIC_DATE));
            }
            if (Chat.Columns.CHAT_MESSAGE_TYPE_TEXT.equalsIgnoreCase(chat.message_type)) {
                holder.bodyTV.setText(mEmojiManager.getExpressionString(getApplicationContext(),
                        chat.message_text, mEmojiTextSize));
                holder.voiceLengthTV.setText("");
            } else if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)) {
                holder.bodyTV.setText("");
                long length = chat.voice_length / 1000;
                if (length < 1) {
                    length += 1;
                }
                holder.voiceLengthTV.setText(getString(R.string.chat_voice, length));
            }
            if (Chat.Columns.CHAT_TYPE_IN.equalsIgnoreCase(chat.type)) {
                if (mActivity instanceof ChatActivity) {
                    holder.nameTV.setVisibility(View.INVISIBLE);
                } else if (mActivity instanceof ChatFavoritesActivity) {
                    holder.nameTV.setText(chat.name);
                    holder.nameTV.setVisibility(View.VISIBLE);
                }
                holder.bodyTV.setBackgroundResource(R.drawable.message_listitem_receive);
                if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)
                        && !chat.read) {
                    holder.imageView.setVisibility(View.VISIBLE);
                } else {
                    holder.imageView.setVisibility(View.INVISIBLE);
                }
                if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)) {
                    drawableStart = (AnimationDrawable) getResources().getDrawable(
                            R.drawable.ic_voice_receive_anim);
                    animationDrawable = drawableStart;
                }
                holder.voiceLengthTV.setVisibility(View.VISIBLE);
            } else {
                holder.nameTV.setText(getString(R.string.me));
                holder.nameTV.setVisibility(View.VISIBLE);
                holder.bodyTV.setBackgroundResource(R.drawable.message_listitem_send);
                View progress = holder.bodyView.findViewById(R.id.progress);
                if (!chat.sent) {
                    if (chat.time_stamp + SEND_TIMEOUT > System.currentTimeMillis()) {
                        showProgress(progress, true);
                        holder.imageView.setVisibility(View.INVISIBLE);
                        holder.voiceLengthTV.setVisibility(View.GONE);
                    } else {
                        showProgress(progress, false);
                        holder.imageView.setVisibility(View.VISIBLE);
                        holder.voiceLengthTV.setVisibility(View.VISIBLE);
                    }
                } else {
                    showProgress(progress, false);
                    holder.imageView.setVisibility(View.INVISIBLE);
                    holder.voiceLengthTV.setVisibility(View.VISIBLE);
                }
                if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)) {
                    drawableEnd = (AnimationDrawable) getResources().getDrawable(
                            R.drawable.ic_voice_send_anim);
                    animationDrawable = drawableEnd;
                }
            }
            holder.bodyTV.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, null,
                    drawableEnd, null);
            if (mCurrentPlayChatId == chat.id) {
                if (animationDrawable != null) {
                    final AnimationDrawable mCurrentPlayAnimationDrawable = animationDrawable;
                    holder.bodyTV.post(new Runnable() {
                        @Override
                        public void run() {
                            mCurrentPlayAnimationDrawable.start();
                        }
                    });
                }
            }
            if (mActivity instanceof ChatActivity) {
                // Set text message to read if it's shown
                if (!chat.read && Chat.Columns.CHAT_TYPE_IN.equalsIgnoreCase(chat.type)
                        && Chat.Columns.CHAT_MESSAGE_TYPE_TEXT.equalsIgnoreCase(chat.message_type)) {
                    holder.bodyTV.post(new Runnable() {
                        @Override
                        public void run() {
                            chat.read = true;
                            Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                        }
                    });
                }
            }
        }

        private void showProgress(View progress, boolean show) {
            if (show) {
                int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
                progress.setVisibility(View.VISIBLE);
                progress.animate().setDuration(shortAnimTime).alpha(1);
            } else {
                progress.setVisibility(View.INVISIBLE);
            }
        }
    }

    private class MenuAdapter extends BaseAdapter {
        private final LayoutInflater mInflater;

        MenuAdapter(LayoutInflater inflater) {
            mInflater = inflater;
        }

        @Override
        public int getCount() {
            return mMenuList.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View resultView =
                    (convertView != null) ? convertView
                            : mInflater.inflate(R.layout.list_item_menu, parent, false);
            final TextView menuTV = resultView.findViewById(R.id.menu);
            menuTV.setText(mMenuList.get(position));
            return resultView;
        }
    }

    protected void playVoice(final String path) {
        Message message = new Message();
        message.what = MSG_PLAY_VOICE;
        message.obj = path;
        mHandler.sendMessage(message);
    }

    private void play(final String path) {
        Log.d(TAG, "path = " + path);
        if (TextUtils.isEmpty(path)) {
            Toast.makeText(getApplicationContext(), R.string.audio_file_expired,
                    Toast.LENGTH_SHORT).show();
            return;
        }
        File file = new File(path);
        if (file.exists()) {
            if (mMediaPlayer != null) {
                try {
                    if (mMediaPlayer.isPlaying()) {
                        stopPlay();
                    }
                } catch (Exception e) {
//                e.printStackTrace();
                }
            }
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mCurrentPlayChatId = 0;
                    try {
                        stopPlay();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            try {
                mMediaPlayer.setDataSource(path);
                mMediaPlayer.prepare();
                mMediaPlayer.start();
                Log.d(TAG, "play started " + path);
            } catch (Exception e) {
                e.printStackTrace();
                stopPlay();
            }
        } else {
            mCurrentPlayChatId = 0;
            if (mChatAdapter != null) { // Stop play voice animation
                mChatAdapter.notifyDataSetChanged();
            }
            Toast.makeText(getApplicationContext(), R.string.audio_file_expired,
                    Toast.LENGTH_SHORT).show();
        }
    }

    protected void stopPlay() {
        if (mMediaPlayer != null) {
            try {
                mMediaPlayer.setOnCompletionListener(null);
                mMediaPlayer.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
            mMediaPlayer.release();
            mMediaPlayer = null;
            if (mChatAdapter != null) { // Stop play voice animation
                mChatAdapter.notifyDataSetChanged();
            }
        }
    }

    protected void onRecordingTimerTick() {
    }

    protected void stopRecordingAndSendMessage() {
    }

    protected void sendChatMessage(Chat chat) {
    }

    private void resendMessage(@NonNull Chat chat) {
        if (mGuardServiceManager != null) {
            chat.sent = false;
            chat.time_stamp = System.currentTimeMillis();
            if (Chat.Columns.CHAT_MESSAGE_TYPE_TEXT.equalsIgnoreCase(chat.message_type)) {
                if (mActivity instanceof ChatFavoritesActivity) {
                    Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI, chat);
                } else {
                    Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                }
                mGuardServiceManager.sendChatMessage(chat.id + "");
                mHandler.sendEmptyMessageDelayed(MSG_UPDATE_UI, SEND_TIMEOUT);
                Log.d(TAG, "resend TextMessage " + chat.id);
            } else if (Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)) {
                if (!TextUtils.isEmpty(chat.server_media_path)) { // MQTT send failure
                    if (mActivity instanceof ChatFavoritesActivity) {
                        Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI, chat);
                    } else {
                        Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                    mGuardServiceManager.sendChatMessage(chat.id + "");
                    mHandler.sendEmptyMessageDelayed(MSG_UPDATE_UI, SEND_TIMEOUT);
                    Log.d(TAG, "resend VoiceMessage " + chat.id);
                } else if (!TextUtils.isEmpty(chat.media_path)) { // QN upload failure
                    File file = new File(chat.media_path);
                    if (file.exists()) {
                        chat.server_media_path = ChatConfig.getServerMediaPath(this, chat);
                        if (mActivity instanceof ChatFavoritesActivity) {
                            Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI,
                                    chat);
                        } else {
                            Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                        }
                        QNHelper.getsQNInstance(mHandler).uploadFile(file, chat,
                                chat.server_media_path.substring(
                                        chat.server_media_path.lastIndexOf("/") + 1));
                        Log.d(TAG, "resend VoiceMessage " + chat.id + "; server_media_path "
                                + chat.server_media_path);
                    } else {
                        Toast.makeText(getApplicationContext(), R.string.audio_file_expired,
                                Toast.LENGTH_SHORT).show();
                        if (mActivity instanceof ChatFavoritesActivity) {
                            Chat.delete(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI,
                                    chat);
                        } else {
                            Chat.delete(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                        }
                        Log.w(TAG, "local audio file is lost, message is deleted");
                    }
                } else { // local file is lost, should delete this message
                    Toast.makeText(getApplicationContext(), R.string.audio_file_expired,
                            Toast.LENGTH_SHORT).show();
                    if (mActivity instanceof ChatFavoritesActivity) {
                        Chat.delete(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI,
                                chat);
                    } else {
                        Chat.delete(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                    Log.w(TAG, "local audio file is lost, message is deleted");
                }
            }
        }
    }

    private void downloadVoiceAndPlay(final Chat chat, final boolean shouldPlay) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                chat.media_path =
                        Utils.downloadFile(chat.server_media_path, ChatConfig.getReceivingFilePath());
                Log.d(TAG, "downloadFile id = " + chat.id + "; media_path = " + chat.media_path);
                if (chat.media_path != null) {
                    chat.voice_length = Utils.getVoiceDuration(chat.media_path);
                    if (mActivity instanceof ChatFavoritesActivity) {
                        Chat.update(getContentResolver(), Chat.Columns.FAVORITE_CONTENT_URI, chat);
                    } else {
                        Chat.update(getContentResolver(), Chat.Columns.CONTENT_URI, chat);
                    }
                }
                if (shouldPlay) {
                    playVoice(chat.media_path); // null means download failed or expired
                }
            }
        }).start();
    }


}
